package com.czmh.etc.onlinepubsys.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.czmh.etc.common.core.annotation.ApiVersion;
import com.czmh.etc.common.core.utils.JwtUtil;
import com.czmh.etc.onlinepubsys.constants.GlobalStatusCode;
import com.czmh.etc.onlinepubsys.constants.HttpStatusCode;
import com.czmh.etc.onlinepubsys.constants.RedisKey;
import com.czmh.etc.onlinepubsys.dto.*;
import com.czmh.etc.onlinepubsys.exceptions.EtcInterpreterException;
import com.czmh.etc.onlinepubsys.json.DetailJson;
import com.czmh.etc.onlinepubsys.json.Json;
import com.czmh.etc.onlinepubsys.json.JsonResult;
import com.czmh.etc.onlinepubsys.json.ListJson;
import com.czmh.etc.onlinepubsys.json.mingchuang.JSONResult;
import com.czmh.etc.onlinepubsys.model.EtcEcardcallbackpage;
import com.czmh.etc.onlinepubsys.model.EtcEcardresult;
import com.czmh.etc.onlinepubsys.model.EtcUser;
import com.czmh.etc.onlinepubsys.request.*;
import com.czmh.etc.onlinepubsys.response.*;
import com.czmh.etc.onlinepubsys.services.EtcInterpreterService;
import com.czmh.etc.onlinepubsys.services.EtcOrderService;
import com.czmh.etc.onlinepubsys.services.EtcUserInfoSevice;
import com.czmh.etc.onlinepubsys.utils.*;
import com.czmh.etc.onlinepubsys.utils.httpclient.HttpUtil;
import com.czmh.etc.onlinepubsys.utils.httpclient.Result;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.DecoderException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @描述：EtcAppController
 * @author： Seven.
 * @创建日期：Jun 9, 2019 10:12:37 PM.
 * @版本：1.0.0
 */
@Slf4j
@RestController
@RequestMapping("/{version}/api/etc")
@Api(tags = "ETC业务移动端接口")
public class EtcAppController {

    @Value("${wx.wxspAppid}")
    private String wxspAppid;
    @Value("${wx.wxspSecret}")
    private String wxspSecret;
    @Value("${wx.jscode2sessionUrl}")
    private String jscode2sessionUrl;
    @Value("${wx.grant_type}")
    private String grant_type;

    @Value("${ecard.clientId}")
    private String clientId;
    @Value("${ecard.aesKey}")
    private String aesKey;
    @Value("${ecard.md5Key}")
    private String md5Key;
    @Value("${ecard.callBackURL}")
    private String callBackURL;
    @Value("${ecard.notifyURL}")
    private String notifyURL;

    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private EtcUserInfoSevice etcUserInfoSevice;
    @Autowired
    private EtcOrderService etcOrderService;
    @Autowired
    private EtcInterpreterService etcInterpreterService;

    @ApiVersion(1)
    @PostMapping("/login")
    @ApiOperation(value = "微信小程序用户登录")
    public DetailJson<LoginInfoResponse> login(@RequestBody WechatLoginRequest request) throws Exception {
        if (StringUtils.isEmpty(request.getCode())) {
            return ResponseJsonUtil.getDetailJson(GlobalStatusCode.FAILED, "无效code");
        }
        log.info("WechatLoginRequest:{}", JSON.toJSONString(request));
        // 向微信服务器使用登录凭证 code 获取 session_key 和 openid
        Map<String, String> params = new HashMap<String, String>(0);
        params.put("appid", wxspAppid);
        params.put("secret", wxspSecret);
        params.put("js_code", request.getCode());
        params.put("grant_type", grant_type);
        Map<String, String> headers = new HashMap<>(0);
        Result result = HttpUtil.httpGet(jscode2sessionUrl, headers, params);
        if (result.getStatusCode() == HttpStatusCode.STATUS_200) {
            //解析相应内容（转换成json对象）
            JSONObject json = JSONObject.parseObject(result.getBody());
            log.info("json:{}", json.toJSONString());
            //获取会话密钥（session_key）
            String session_key = json.get("session_key").toString();
            String userinfo = "";
            if (null != request.getEncryptedData()) {
                userinfo = AesUtil.decrypt(request.getEncryptedData(), session_key, request.getIv(), "UTF-8");
            } else {
                userinfo = request.getUserInfo();
            }
            log.info("userinfo:{}", userinfo);
            if (StringUtils.isNotEmpty(userinfo)) {
                JSONObject userInfoJSON = JSONObject.parseObject(userinfo);
                userInfoJSON.put("openId", json.get("openid"));
                userInfoJSON.put("unionId", json.get("unionid"));
                log.info("/login:{}", userInfoJSON.toJSONString());
                // 保存用户信息
                EtcUser etcUser = etcUserInfoSevice.saveUserInfo(userInfoJSON);
                LoginInfoResponse data = new LoginInfoResponse();
                String user_id = etcUser.getUser_id();
                data.setUser_id(user_id);
                data.setOpenid(json.getString("openid"));
                // 生成用户token
                String token = JwtUtil.createToken(user_id);
                redisUtil.set(RedisKey.USER_SESSION_KEY + user_id, session_key, JwtUtil.EXPIRE_TIME);
                redisUtil.set(RedisKey.USER_LOGIN_KEY + user_id, token, JwtUtil.EXPIRE_TIME);
                redisUtil.set(RedisKey.APP_TOKEN + token, token, 1728000);
                data.setAccess_token(token);
                return ResponseJsonUtil.getDetailJson(data);
            } else {
                return ResponseJsonUtil.getDetailJson(GlobalStatusCode.FAILED, "登录失败！");
            }
        } else {
            return ResponseJsonUtil.getDetailJson(GlobalStatusCode.FAILED, "登录失败！！");
        }
    }

    @ApiVersion(1)
    @PostMapping("/getPhoneNumber")
    @ApiOperation(value = "获取小程序用户手机号")
    public JSONResult getPhoneNumber(@RequestBody GetPhoneNumberRequest request) throws Exception {
        JSONResult jsonResult = new JSONResult();
        String user_id = request.getUser_id();
        if (StringUtils.isEmpty(user_id)) {
            jsonResult.setCode(JSONResult.FAIL);
            jsonResult.setMessage("请先登录");
            return jsonResult;
        }
        //获取会话密钥（session_key)
        String session_key = redisUtil.get(RedisKey.USER_SESSION_KEY + user_id).toString();
        String userinfo = AesUtil.decrypt(request.getEncryptedData(), session_key, request.getIv(), "UTF-8");
        log.info("解密数据：=====" + userinfo);
        if (StringUtils.isNotEmpty(userinfo)) {
            JSONObject userInfoJSON = JSONObject.parseObject(userinfo);
            String phoneNumber = userInfoJSON.getString("phoneNumber");
            // 保存用户信息
            UpdateUserInfo userInfo = new UpdateUserInfo();
            userInfo.setUser_id(user_id);
            userInfo.setUser_phone(phoneNumber);
//            etcUserInfoSevice.updateUserInfo(userInfo);
            jsonResult.setCode(JSONResult.SUCCESS);
            jsonResult.setRspData(JSON.toJSONString(userInfo));
            return jsonResult;
        } else {
            jsonResult.setCode(JSONResult.FAIL);
            jsonResult.setMessage("获取手机号失败");
            return jsonResult;
        }
    }

    @ApiVersion(1)
    @PostMapping("/apply")
    @ApiOperation(value = "ETC线上发行申请")
    public DetailJson<RegisterInfoResponse> apply(@RequestBody EtcInfoRequest request) {
        etcUserInfoSevice.submitApplyInfo(request.getUser_id(), request.getApply(), request.getIdcard(), request.getVehiclelicense());
        RegisterInfoResponse data = new RegisterInfoResponse();
        data.setUser_id(request.getUser_id());
        return ResponseJsonUtil.getDetailJson(data);
    }

    @ApiVersion(1)
    @PostMapping("/sendverificationcode")
    @ApiOperation(value = "发送验证码")
    public JSONResult sendverificationcode(@RequestBody SendverificationcodeRequest request) {
        JSONResult result = new JSONResult();
        if (redisUtil.hasKey(request.getPhone())) {
            result.setCode("700");
            result.setMessage("\"短信发送频繁，请稍后重试！\"");
        } else {
            String code = AliSmsUtil.sendPhoneVerificationcode(request.getPhone());
            if (!GlobalStatusCode.SUCCESS.equals(code)) {
                result.setCode("700");
                result.setMessage("短信发送失败");
            }
        }
        return result;
    }

    @ApiVersion(1)
    @PostMapping("/submitaddr")
    @ApiOperation(value = "填写收货地址")
    public DetailJson<SubmitaddrResponse> submitaddr(@RequestBody SubmitaddrRequest request) {
        // 手机验证码
        String verificationcode = request.getVerificationcode();
        String code = redisUtil.get(request.getAddr().getAd_consigneephone()).toString();
        if (StringUtils.isNotEmpty(verificationcode) && StringUtils.isNotEmpty(code) && (verificationcode.equals(code))) {
            String orderId = etcOrderService.submitaddrOrder(request.getAddr(), "");
            SubmitaddrResponse data = new SubmitaddrResponse();
            data.setOrder_id(orderId);
            data.setUser_id(request.getAddr().getUser_id());
            return ResponseJsonUtil.getDetailJson(data);
        } else {
            return ResponseJsonUtil.getDetailJson(GlobalStatusCode.FAILED, "验证码错误");
        }
    }

    @ApiVersion(1)
    @GetMapping("/ecard/apicardparam")
    @ApiOperation(value = "获取交通银行信用卡网络发卡请求参数")
    public DetailJson<EcardApicardparamResponse> ecardApicardparam() throws Exception {
        EcardApicardparamResponse responseData = new EcardApicardparamResponse();
        EcardApicardparamDto param = new EcardApicardparamDto();
        param.setCallBackURL(callBackURL);
        param.setNotifyURL(notifyURL);
        Attach attach = new Attach();
//        attach.setApplyCarNo(apply_carlicence);
//        attach.setApplyCarPlateColor(apply_carlicencetyoe);
        param.setAttach(attach);
        String jsonStr = JSON.toJSONString(param);
        log.info("封装参数：" + jsonStr);
        String encode = URLEncoder.encode(jsonStr, "UTF-8");
        String data = AESUtils.Encrypt(encode, aesKey);
        String sign = SignUtils.md5(data + md5Key);
        String requestParam = "data=" + data + "&sign=" + sign + "&trackCode=&clientId=" + clientId;
        responseData.setParam(requestParam);
        responseData.setSerialNum(param.getSerialNum());
        return ResponseJsonUtil.getDetailJson(responseData);
    }

    @ApiVersion(1)
    @GetMapping("/ecard/callback")
    public void ecardCallback(HttpServletRequest request, HttpServletResponse response) throws Exception {
        String data = RequestUtil.getString(request, "data");
        String bank_type = RequestUtil.getString(request, "bank_type");
        String requestSign = RequestUtil.getString(request, "sign");
        String authorization = RequestUtil.getHeader(request, "Authorization");
        String sign = SignUtils.md5(data + md5Key);
        // 验签成功
        if (sign.equals(requestSign)) {
            String decryptData = AESUtils.Decrypt(data, aesKey);
            String paramData = URLDecoder.decode(decryptData, "UTF-8");
            log.info("ecardCallback====回调收到解码参数：" + paramData);
            EtcEcardcallbackpage etcEcardcallbackpage = JSONObject.parseObject(paramData, EtcEcardcallbackpage.class);
            etcUserInfoSevice.saveEcardCallbackPageParam(etcEcardcallbackpage, authorization);
        } else {
            log.error("签名错误");
        }
    }

    @ApiVersion(1)
    @PostMapping("/ecard/notify")
    public void ecardNotify(HttpServletRequest request, HttpServletResponse response) throws Exception {
        String data = RequestUtil.getString(request, "data");
        String bank_type = RequestUtil.getString(request, "bank_type");
        String requestSign = RequestUtil.getString(request, "sign");
        String sign = SignUtils.md5(data + md5Key);
        // 验签成功
        if (sign.equals(requestSign)) {
            String decryptData = AESUtils.Decrypt(data, aesKey);
            String paramData = URLDecoder.decode(decryptData, "UTF-8");
            log.info("ecardNotify======回调收到解码参数：" + paramData);
            EtcEcardresult etcEcardresult = JSONObject.parseObject(paramData, EtcEcardresult.class);
            etcUserInfoSevice.saveEcardNotifyParam(etcEcardresult);
        } else {
            log.info("签名错误");
        }
    }

    @ApiVersion(1)
    @GetMapping("/ecard/getcheckinfo")
    @ApiOperation(value = "获取该用户信用卡登记信息")
    public JsonResult getcheckinfo(@RequestParam @ApiParam(name = "当前登录用户id", required = true) String userId) throws Exception {
        return etcUserInfoSevice.getEcardCheckin(userId);
    }

    @ApiVersion(1)
    @GetMapping("/ecard/checkcreditcard")
    @ApiOperation(value = "获取当前用户是否登记过该信用卡的信息，如果有则直接返回登记的信息")
    public JsonResult checkcreditcard(@RequestParam @ApiParam(name = "当前登录用户id", required = true) String userId, @RequestParam @ApiParam(name = "申办的信用卡：1表示交通银行信用卡，2表示xx银行信用卡；", required = true) Integer card_type) throws Exception {
        return etcUserInfoSevice.checkcreditcard(userId, card_type);
    }

    @ApiVersion(1)
    @GetMapping("/ecard/submitinfo")
    @ApiOperation(value = "跳转至信用卡信息填写页面")
    public JsonResult submitinfo(@RequestParam @ApiParam(name = "当前登录用户id", required = true) String userId, @RequestParam @ApiParam(name = "信用卡类型：1是交行信用卡", required = true) Integer card_type, HttpServletRequest request) throws Exception {
        String serialNum = etcUserInfoSevice.saveEcardView(userId, card_type, RequestUtil.getRemoteIp(request));
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("serialNum", serialNum);
        return JsonResultUtil.toResult(map);
    }

    @ApiVersion(1)
    @PostMapping("/ecard/checkin")
    @ApiOperation(value = "登记信息，确认办理信用卡的姓名和身份证")
    public JsonResult ecardCheckin(@RequestBody EtcEcardcheckinEditRequest request, HttpServletResponse response) throws Exception {
        return etcUserInfoSevice.saveEcardCheckin(request);
    }

    @ApiVersion(1)
    @PostMapping("/ecard/checkexchangeNo")
    @ApiOperation(value = "校验获取现金兑换码")
    public JsonResult checkexchangeNo(@RequestBody CheckExchangeNoRequest request, HttpServletResponse response) throws Exception {
        return etcUserInfoSevice.checkexchangeNo(request);
    }

    @ApiVersion(1)
    @PostMapping("/ecard/updatexchangeNo/{serialNum}")
    @ApiOperation(value = "核销兑换码")
    public JsonResult updatexchangeNo(@PathVariable String serialNum) throws Exception {
        return etcUserInfoSevice.updatexchangeNo(serialNum);
    }

    @ApiVersion(1)
    @PostMapping("/registerinfo")
    @ApiOperation(value = "注册高管局用户及车辆信息")
    public Json registerinfo(@RequestBody RegisterinfoRequest registerinfoRequest) throws Exception {
        log.debug("前端提交参数：" + JSON.toJSONString(registerinfoRequest));
        etcInterpreterService.registerinfo(registerinfoRequest.getUser_id(), registerinfoRequest.getApply_id());
        return ResponseJsonUtil.getJson();
    }

    @ApiVersion(1)
    @PostMapping("/cardsecsend")
    @ApiOperation(value = "卡二发，备注：需要调用2次该接口，第一次返回写入0016文件信息，第二次返回写入0015文件信息")
    public DetailJson<UserCardInfoResponse> cardSecSend(@RequestBody CardSecSendRequest cardSecSendRequest) throws Exception {
        log.info("前端提交的参数：" + JSON.toJSONString(cardSecSendRequest));
        EtcInterpreterMessageDto message = etcInterpreterService.cardSecSend(
                cardSecSendRequest.getUser_id(),
                cardSecSendRequest.getApply_id(),
                cardSecSendRequest.getObu_id(),
                cardSecSendRequest.getCardId(),
                cardSecSendRequest.getCardType(),
                cardSecSendRequest.getCardVersion(),
                cardSecSendRequest.getUserType(),
                cardSecSendRequest.getRamdom(),
                cardSecSendRequest.getFileType());
        UserCardInfoResponse data = new UserCardInfoResponse();
        JSONObject jsonObject = JSONObject.parseObject(message.getResultStr());
        JSONObject dataObject = jsonObject.getJSONObject("data");
        data.setUserCardInfo(dataObject.getString("UserCardInfo"));
        log.debug("卡二发返回参数：{}", JSON.toJSONString(data));
        return ResponseJsonUtil.getDetailJson(data);
    }

    @ApiVersion(1)
    @PostMapping("/obusecsend")
    @ApiOperation(value = "OBU二发，备注：改接口需要调用两次，第一次调用需要传入文件类型fileType为1:系统信息文件，这时返回系统信息写入指令；第二次调用时需要传入文件类型fileType为2:系统信息文件，这时返回应用信息写入指令")
    public DetailJson<ObuSecSendResponse> obuSecSend(@RequestBody ObuSecSendRequest obuSecSendRequest) throws EtcInterpreterException, Exception {
        log.debug("前端提交参数：" + JSON.toJSONString(obuSecSendRequest));
        // 先调用9104注册obu再调用9139发行（opertype：1，filetype：1）
        EtcInterpreterMessageDto message = etcInterpreterService.obuSecSend(
                obuSecSendRequest.getUser_id(),
                obuSecSendRequest.getApply_id(),
                obuSecSendRequest.getObuId(),
                obuSecSendRequest.getUserType(),
                obuSecSendRequest.getFileType(),
                obuSecSendRequest.getRamdom());
        ObuSecSendResponse data = new ObuSecSendResponse();
        JSONObject jsonObject = JSONObject.parseObject(message.getResultStr());
        JSONObject dataObject = jsonObject.getJSONObject("data");
        String obuInfo = dataObject.getString("OBUInfo");
        data.setoBUInfo(obuInfo);
        log.debug("OBU二发返回指令：{}", obuInfo);
        return ResponseJsonUtil.getDetailJson(data);
    }

    @ApiVersion(1)
    @PostMapping("/obuactivation")
    @ApiOperation(value = "OBU激活")
    public DetailJson<ObuactivationResponse> obuactivation(@RequestBody ObuactivationRequest request) throws Exception {
        log.debug("前端提交参数：" + JSON.toJSONString(request));
        ObuactivationResponse data = etcInterpreterService.obuactivation(request);
        log.debug("OBU激活返回指令：{}", JSON.toJSONString(data));
        return ResponseJsonUtil.getDetailJson(data);
    }

    @ApiVersion(1)
    @PostMapping("/obuconfirm")
    @ApiOperation(value = "OBU发行结果确认")
    public Json obuconfirm(@RequestBody ObuconfirmRequest request) throws Exception {
        log.debug("前端提交参数：" + JSON.toJSONString(request));
        etcInterpreterService.obuconfirm(request.getUser_id(), request);
        return ResponseJsonUtil.getJson();
    }

    @ApiVersion(1)
    @GetMapping("/applyprogress")
    @ApiOperation(value = "申办进度查询")
    public ListJson<ApplyProgressDto> applyprogress(@ApiParam(name = "订单id") @RequestParam String order_id) {
        List<ApplyProgressDto> data = etcOrderService.getApplyProgress(order_id);
        return ResponseJsonUtil.getListJson(data, 0);
    }

    @ApiVersion(1)
    @GetMapping("/confirmgoods")
    @ApiOperation(value = "确认收货")
    public Json confirmgoods(@ApiParam(name = "订单id") @RequestParam String order_id) {
        etcOrderService.confirmgoods(order_id);
        return ResponseJsonUtil.getJson();
    }

    @ApiVersion(1)
    @GetMapping("/applylist")
    @ApiOperation(value = "获取该用户的发行申请列表")
    public ListJson<ApplyListDto> applylist(@ApiParam(name = "用户id") @RequestParam String user_id) {
        List<ApplyListDto> rows = etcOrderService.applylist(user_id);
        return ResponseJsonUtil.getListJson(rows, 0);
    }

    @ApiVersion(1)
    @PostMapping(value = "/decodeobuinfo")
    @ApiOperation(value = "获取OBU转码信息")
    public DetailJson<ObuInfo> decodeobuinfo(@RequestBody ObuInfo obuInfo) throws UnsupportedEncodingException, DecoderException {
        log.info("OBU获取前端信息: " + JSON.toJSONString(obuInfo));
        ObuInfo data = ObuInfoUtil.decodeObuInfo(obuInfo);
        return ResponseJsonUtil.getDetailJson(data);
    }
}
